﻿/*
 * ********************************************************************************************************************
 *
 *               iFHS7.
 *              ;BBMBMBMc                  rZMBMBR              BMB
 *              MBEr:;PBM,               7MBMMEOBB:             BBB                       RBW
 *     XK:      BO     SB.     :SZ       MBM.       c;;     ir  BBM :FFr       :SSF:    ;xBMB:r   iuGXv.    i:. iF2;
 *     DBBM0r.  :D     S7   ;XMBMB       GMBMu.     MBM:   BMB  MBMBBBMBMS   WMBMBMBBK  MBMBMBM  BMBRBMBW  .MBMBMBMBB
 *      :JMRMMD  ..    ,  1MMRM1;         ;MBMBBR:   MBM  ;MB:  BMB:   MBM. RMBr   sBMH   BM0         UMB,  BMB.  KMBv
 *     ;.   XOW  B1; :uM: 1RE,   i           .2BMBs  rMB. MBO   MBO    JMB; MBB     MBM   BBS    7MBMBOBM:  MBW   :BMc
 *     OBRJ.SEE  MRDOWOR, 3DE:7OBM       .     ;BMB   RMR7BM    BMB    MBB. BMB    ,BMR  .BBZ   MMB   rMB,  BMM   rMB7
 *     :FBRO0D0  RKXSXPR. JOKOOMPi       BMBSSWBMB;    BMBB:    MBMB0ZMBMS  .BMBOXRBMB    MBMDE RBM2;SMBM;  MBB   xBM2
 *         iZGE  O0SHSPO. uGZ7.          sBMBMBDL      :BMO     OZu:BMBK,     rRBMB0;     ,EBMB  xBMBr:ER.  RDU   :OO;
 *     ,BZ, 1D0  RPSFHXR. xWZ .SMr                  . .BBB
 *      :0BMRDG  RESSSKR. 2WOMBW;                   BMBMR
 *         i0BM: SWKHKGO  MBDv
 *           .UB  OOGDM. MK,                                          Copyright (c) 2015-2019.  斯伯坦机器人
 *              ,  XMW  ..
 *                  r                                                                     All rights reserved.
 *
 * ********************************************************************************************************************
 */

using MongoDB.Driver;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Xceed.Wpf.AvalonDock.Layout;

namespace MongoPI
{
    /// <summary>
    /// DatabaseExplorer.xaml 的交互逻辑
    /// </summary>
    public partial class DatabaseExplorer : UserControl
    {
        public LayoutDocumentPane DocumentPane;

        /// <summary>
        /// 数据库资源管理器构造函数。
        /// </summary>
        public DatabaseExplorer()
        {
            InitializeComponent();

            ServerConnectInfo info = new ServerConnectInfo();
            info.ServerName = "localhost";
            info.Server = "localhost";
            DbExplorer.ConnectAdd(info);

            return;
        } // Function DatabaseExplorer()

        #region DbExplorer事件
        /// <summary>
        /// 鼠标双击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DbExplorer_MouseDoubleClient(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            TreeViewItem treeViewItem = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;
            if (null == treeViewItem)
            {
                return;
            }

            treeViewItem.Focus();
            e.Handled = true;
            var itemData = treeViewItem.DataContext as ExplorerViewItem;
            try
            {
                switch(itemData.NodeType)
                {
                    case ExplorerViewItem.ItemType.Collection:          // 集合
                        OpenCollection(GetServerName(itemData), itemData.BindObject as IMongoDatabase, itemData.Name);
                        break;

                    case ExplorerViewItem.ItemType.UserList:            // 用户列表
                        OpenUserManage(GetServerName(itemData), itemData.BindObject as IMongoDatabase);
                        break;

                    case ExplorerViewItem.ItemType.RoleList:            // 角色列表
                        OpenRoleManage(GetServerName(itemData), itemData.BindObject as IMongoDatabase);
                        break;

                    default:
                        break;
                }
            }
            catch (Exception e1)
            {
                // DO NOTHING
            }
            return;
        } // Function DbExplorer_MouseDoubleClient()

        /// <summary>
        /// 点击鼠标右键，设置弹出菜单
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        private void DbExplorer_PreviewMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            TreeViewItem treeViewItem = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;
            if (null == treeViewItem)
            {
                DbExplorer.ContextMenu = null;
                return;
            }

            treeViewItem.Focus();
            e.Handled = true;
            var itemData = treeViewItem.DataContext as ExplorerViewItem;
            try
            {
                DbExplorer.ContextMenu = this.FindResource($"Menu{itemData.NodeType}") as ContextMenu;
            }
            catch (Exception e1)
            {
                // 如果取不到对应的弹出菜单，则设置弹出菜单为空
                DbExplorer.ContextMenu = null;
            }

            return;
        } // Function DatabaseTreeView_PreviewMouseDown()

        private static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
        {
            while (source != null && source.GetType() != typeof(T))
            {
                source = VisualTreeHelper.GetParent(source);
            }

            return source;
        } // Function VisualUpwardSearch

        #endregion

        #region UI命令
        #region 服务器命令  
        /// <summary>
        /// 连接服务器命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdServerConnect_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("CmdServerConnect_Executed");
            return;
        } // Function CmdMongoConnect_Executed()

        /// <summary>
        /// 是否可以执行连接服务器命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdServerConnect_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
            return;
        } // Function CmdServerConnect_CanExecute()

        /// <summary>
        /// 断开服务器连接命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdServerDisconnect_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("CmdServerDisconnect_Executed");
            return;
        } // Function CmdServerDisconnect_Executed()

        /// <summary>
        /// 是否可以执行断开服务器连接命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdServerDisconnect_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
            return;
        } // Function CmdServerDisconnect_CanExecute()
        #endregion

        #region 数据库命令
        /// <summary>
        /// 添加数据库命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdDatabaseAdd_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            var dlg = new DatabaseAddDialog();
            dlg.ShowDialog();
            if (dlg.DialogResult == true)
            {
                ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
                if (null == itemData)
                {
                    return;
                }

                MongoClient client = itemData.BindObject as MongoClient;
                if (null != client)
                {
                    client.GetDatabase(dlg.DatabaseName);
                    DbExplorer.DatabaseAdd(client, dlg.DatabaseName, itemData);
                }
            }
            return;
        } // Function CmdDatabaseAdd_Executed()

        /// <summary>
        /// 判断是否可以执行添加数据库命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdDatabaseAdd_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
            e.CanExecute = (itemData == null ? false : (itemData.NodeType == ExplorerViewItem.ItemType.Server));
            return;
        } // Function CmdDatabaseAdd_CanExecute()

        /// <summary>
        /// 删除数据库命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdDatabaseDrop_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            try
            {
                ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
                string msg = string.Format("MsgDatabaseDrop".Resource(), itemData.Name);
                // 如果用户不删除，则返回
                if (MessageBox.Show(msg, "TitleDatabaseDrop".Resource(), MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) != MessageBoxResult.Yes)
                {
                    return;
                }
                MongoClient client = (itemData.BindObject as IMongoDatabase).Client as MongoClient;
                client.DropDatabase(itemData.Name);
                itemData.Parent.Children.Remove(itemData);
            }
            catch (Exception e1)
            {
                MessageBox.Show(e1.Message);
            }
            return;
        } // Function CmdDatabaseDrop_Executed()

        /// <summary>
        /// 判断是否可以执行删除数据库命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdDatabaseDrop_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
            e.CanExecute = (itemData == null ? false : (itemData.NodeType == ExplorerViewItem.ItemType.Database));
            return;
        } // Function CmdDatabaseDrop_CanExecute()

        #endregion

        #region 集合命令
        /// <summary>
        /// 判断是否可以执行删除集合命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdCollectionAdd_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            var dlg = new CollectionAddDialog();
            dlg.ShowDialog();
            return;
            if (dlg.DialogResult == true)
            {
                try
                {
                    ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
                    if (itemData.NodeType == ExplorerViewItem.ItemType.Database)
                    {
                        itemData = itemData.Children.First(p=>p.NodeType == ExplorerViewItem.ItemType.CollectionList);
                    }
                    IMongoDatabase database = itemData.BindObject as IMongoDatabase;
                    database.CreateCollection(dlg.CollectionName);
                    DbExplorer.CollectionAdd(database, itemData, dlg.CollectionName);
                }
                catch (Exception e1)
                {
                    MessageBox.Show(e1.Message);
                }
            }

            return;
        } // Function CmdCollectionAdd_Executed()

        /// <summary>
        /// 判断是否可以执行删除集合命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdCollectionAdd_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
            e.CanExecute = (itemData == null ? false : (itemData.NodeType == ExplorerViewItem.ItemType.CollectionList ||
                                                        itemData.NodeType == ExplorerViewItem.ItemType.Database));
            return;
        } // Function CmdCollectionAdd_CanExecute()

        /// <summary>
        /// 判断是否可以执行清空集合命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdCollectionClear_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("CmdCollectionClear_Executed");
            return;
        } // Function CmdCollectionClear_Executed()

        /// <summary>
        /// 判断是否可以执行清空集合命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdCollectionClear_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
            e.CanExecute = (itemData == null ? false : (itemData.NodeType == ExplorerViewItem.ItemType.Collection));
            return;
        } // Function CmdCollectionClear_CanExecute()

        /// <summary>
        /// 判断是否可以执行删除集合命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdCollectionDrop_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            try
            {
                ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
                string msg = string.Format("MsgCollectionDrop".Resource(), itemData.Name);
                // 如果用户不删除，则返回
                if (MessageBox.Show(msg, "TitleCollectionDrop".Resource(), MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) != MessageBoxResult.Yes)
                {
                    return;
                }
                IMongoDatabase database = itemData.BindObject as IMongoDatabase;
                database.DropCollection(itemData.Name);
                itemData.Parent.Children.Remove(itemData);
            }
            catch (Exception e1)
            {
                MessageBox.Show(e1.Message);
            }
            return;
        } // Function CmdCollectionDrop_Executed()

        /// <summary>
        /// 判断是否可以执行删除集合命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdCollectionDrop_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
            e.CanExecute = (itemData == null ? false : (itemData.NodeType == ExplorerViewItem.ItemType.Collection));
            return;
        } // Function CmdCollectionDrop_CanExecute()

        /// <summary>
        /// 重命名集合命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdCollectionRename_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("CmdCollectionRename_Executed");
            return;
        } // Function CmdCollectionRename_Executed()

        /// <summary>
        /// 判断是否可以执行重命名集合命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdCollectionRename_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
            e.CanExecute = (itemData == null ? false : (itemData.NodeType == ExplorerViewItem.ItemType.Collection));
            return;
        } // Function CmdCollectionRename_CanExecute()
        #endregion

        #region 用户命令
        /// <summary>
        /// 用户管理命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdUserManage_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            try
            {
                ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
                IMongoDatabase database = itemData.BindObject as IMongoDatabase;
                OpenUserManage(GetServerName(itemData), database);
            }
            catch (Exception e1)
            {
                // DO NOTHING
            }
            return;
        } // Function CmdUserManage_Executed()

        /// <summary>
        /// 判断是否可以执行用户管理命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdUserManage_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
            e.CanExecute = (itemData == null ? false : (itemData.NodeType != ExplorerViewItem.ItemType.Server));
            return;
        } // Function CmdUserManage_CanExecute()
        #endregion

        #region 角色命令
        /// <summary>
        /// 角色管理命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdRoleManage_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            try
            {
                ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
                IMongoDatabase database = itemData.BindObject as IMongoDatabase;
                OpenRoleManage(GetServerName(itemData), database);
            }
            catch (Exception e1)
            {
                // DO NOTHING
            }

            return;
        } // Function CmdRoleManage_Executed()

        /// <summary>
        /// 判断是否可以执行角色管理命令
        /// </summary>
        /// <param name="sender">事件的发送者</param>
        /// <param name="e">事件参数</param>
        public void CmdRoleManage_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
        {
            ExplorerViewItem itemData = DbExplorer.SelectedItem as ExplorerViewItem;
            e.CanExecute = (itemData == null ? false : (itemData.NodeType != ExplorerViewItem.ItemType.Server));
            return;
        } // Function CmdRoleManage_CanExecute()
        #endregion

        #endregion

        /// <summary>
        /// 打开文档
        /// </summary>
        /// <param name="title">文档标题</param>
        /// <param name="content">文件对象</param>
        /// <param name="iconUri">图标</param>
        private void DocumentOpen(object content, string title, string iconUri = null)
        {
            LayoutDocument document = new LayoutDocument();
            document.Title = title;
            document.ContentId = "abc";
            document.Content = content;
            if (null != iconUri)
            {
                document.IconSource = new BitmapImage(new Uri(iconUri, UriKind.Relative));
            }
            
            document.IsActive = true;
            DocumentPane.Children.Add(document);
            return;
        } // Function OpenDocument()

        /// <summary>
        /// 打开用户管理器
        /// </summary>
        /// <param name="database">数据库对象</param>
        private void OpenUserManage(string server, IMongoDatabase database)
        {
            DocumentOpen(new UserManageView(server, database), "TitleUserManage".Resource(), "/Images/IconUsers.png");
            return;
        } // Function OpenUserManage()

        /// <summary>
        /// 打开角色管理器
        /// </summary>
        /// <param name="database">数据库对象</param>
        private void OpenRoleManage(string server, IMongoDatabase database)
        {
            DocumentOpen(new UserManageView(server, database), "TitleRoleManage".Resource(), "/Images/IconRoles.png");
            return;
        } // Function OpenRoleManage()

        /// <summary>
        /// 打开集合编辑器
        /// </summary>
        /// <param name="database">数据库对象</param>
        /// <param name="collection">集合名称</param>
        private void OpenCollection(string server, IMongoDatabase database, string collection)
        {
            DocumentOpen(new CollectionView(server, database, collection), collection, "/Images/IconCollection.png");
            return;
        } // Function OpenRoleManage()

        /// <summary>
        /// 获得节点对应的服务器
        /// </summary>
        /// <param name="itemData"></param>
        /// <returns></returns>
        private string GetServerName(ExplorerViewItem itemData)
        {
            while(itemData != null)
            {
                if (itemData.NodeType == ExplorerViewItem.ItemType.Server)
                {
                    return itemData.Name;
                }

                itemData = itemData.Parent;
            }
            return "";
        } // Function GetServerName()
    } // Class DatabaseExplorer
} // Namespace MongoPI
